package com.youlu.campus.service.ranking.impl;

import com.alibaba.fastjson.JSON;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.community.RankingList;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.entity.QQMiniUserPO;
import com.youlu.campus.service.ranking.entity.UserActivityPointRanking;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.UserPointRanking;
import com.youlu.campus.entity.VO.RankingListQueryVO;
import com.youlu.campus.entity.VO.req.RankingListResVO;
import com.youlu.campus.entity.WechatMiniUserPO;
import com.youlu.campus.service.base.LockService;
import com.youlu.campus.service.ranking.UserPointRankingService;
import com.youlu.campus.service.visitor.VisitorUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.youlu.campus.base.base.Constants.defaultHead;

@Slf4j
@Service
public class UserPointRankingServiceImpl implements UserPointRankingService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private VisitorUserService visitorUserService;
    @Autowired
    private LockService lockService;


    @Override
    public RankingListResVO getUserTaskRanking(RankingListQueryVO req, UserPO userPO) {
        log.info(":>>> 获取用户活动积分排行榜:{}", JSON.toJSONString(req));
        if (Objects.isNull(req)) {
            log.error(":>>> 获取活动积分排行榜参数错误=");
            throw new BusinessException("获取活动积分排行榜参数错误");
        }
        req.setUserPO(userPO);
        return getUserPointRankList(req, userPO);
    }

    @Async
    @Override
    public void updatePoint(UserPO userPO, String activityId, Integer point) {
        log.info(":>>> 开始更新用户:{} 积分排行榜activityId:{},{}", userPO == null ? null : userPO.getId(), activityId, point);
        try {
            boolean lock = lockService.tryLock(String.format("com.luyou.updatePoint:%s", userPO.getId()), 60, TimeUnit.SECONDS);
            log.info(":>>> 获取用户:{} 积分排行榜锁结果:{}", userPO.getId(), lock);
            if (!lock) {
                return;
            }
            Query queryQQ = new Query().addCriteria(Criteria.where("accountInfoId").is(userPO.getId()));
            if ("wechat-mini".equals(userPO.getCurrentPlatform())) {
                WechatMiniUserPO wechatMiniUserPO = mongoTemplate.findOne(queryQQ, WechatMiniUserPO.class);
                if (Objects.nonNull(wechatMiniUserPO)) {
                    userPO.setRankAvatarUrl(wechatMiniUserPO.getAvatarUrl());
                    userPO.setRankNickName(wechatMiniUserPO.getRankNickName());
                }
            } else {
                QQMiniUserPO qqMiniUserPO = mongoTemplate.findOne(queryQQ, QQMiniUserPO.class);
                if (Objects.nonNull(qqMiniUserPO)) {
                    userPO.setRankAvatarUrl(qqMiniUserPO.getAvatarUrl());
                    userPO.setRankNickName(qqMiniUserPO.getRankNickName());
                }
            }
            UserPointRanking db = this.find(userPO.getId(), userPO.getProvince(), activityId);
            if (Objects.isNull(db)) {
                log.info(":>>> 用户积分排行榜不存在新建:{}", userPO.getId());
                db = new UserPointRanking();
                db.setActivityId(activityId);
                db.setUserId(userPO.getId());
                db.setImageUrl(userPO.getRankAvatarUrl());
                db.setName(userPO.getRankNickName());
                db.setQuantity(Double.valueOf(point + ""));
                db.setActivityId(activityId);
                db.setCreatedTime(new Date());
                db.setUniversityId(userPO.getUniversityId());
                mongoTemplate.insert(db);
                return;
            }
            Query query = new Query().addCriteria(Criteria.where("id").is(db.getId()));
            Update update = new Update();
            update.inc("quantity", Double.valueOf(point + ""));
            update.set("updatedTime", new Date());
            UpdateResult updateResult = mongoTemplate.updateFirst(query, update, UserPointRanking.class);
            log.info(":>>> 用户积分排行榜存在更新:{},结果:{}", userPO.getId(), updateResult.getModifiedCount());
        } catch (Exception e) {
            log.error(":>>> 更新积分排行榜错误:{}", e);
        } finally {
            lockService.unLock(String.format("com.luyou.updatePoint:%s", userPO.getId()));
        }
    }

    @Override
    public UserPointRanking find(String userId, String province, String activityId) {
        Query query = new Query().addCriteria(Criteria.where("userId").is(userId));
        return mongoTemplate.findOne(query, UserPointRanking.class);
    }

    @Override
    public UserActivityPointRanking findByUserIdAndActivityId(String userId, String activityId) {
        Query query = new Query().addCriteria(Criteria.where("userId").is(userId)).addCriteria(Criteria.where("activityId").is(activityId));
        return mongoTemplate.findOne(query, UserActivityPointRanking.class);
    }

    /**
     * 获取用户积分总榜总榜
     *
     * @param req
     * @param userPO
     * @return
     */
    private RankingListResVO getUserPointRankList(RankingListQueryVO req, UserPO userPO) {
        RankingListResVO rankingListResVO = new RankingListResVO();
        try {
            if (Objects.isNull(req.getPageSize())) {
                req.setPageSize(10);
            }
            Query query = new Query();
            Sort sort = Sort.by(Sort.Direction.DESC, "quantity");
            query.with(sort);
            query.limit(req.getPageSize());
            Long count = mongoTemplate.count(query, UserPointRanking.class);
            Integer totalPages = 0;
            if (count.intValue() == 0) {
                totalPages = 0;
            } else {
                if (count.intValue() % req.getPageSize() == 0) {
                    totalPages = count.intValue() / req.getPageSize();
                } else {
                    totalPages = count.intValue() / req.getPageSize() + 1;
                }
            }
            log.info(":>>> 用户积分排行榜数量:{},总页数:{},每页大小:{},当前页:{}", count, totalPages, req.getPageSize(), req.getPage());
            PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
            List<UserPointRanking> rankings = null;
            if (totalPages < req.getPage()) {
                rankings = new ArrayList<>();
                log.info(":>>> 排行榜总页数:{} 是最后一页:{}", totalPages, req.getPage());

            } else {
                rankings = mongoTemplate.find(query.with(pageRequest), UserPointRanking.class);

            }
            List<RankingList> rankingLists = new ArrayList<>();
            boolean in = false;
            int order = 1;
            int uOrder = 1001;
            int orderNN = (req.getPage() - 1) * req.getPageSize() + 1;
            List<String> userIds = new ArrayList<>();
            for (UserPointRanking d : rankings) {
                if (StringUtils.isNotBlank(d.getUserId())) {
                    userIds.add(d.getUserId());
                }
            }
            HashMap<String, UserPO> userPOHashMap = visitorUserService.getByUserIds(userIds);
            for (UserPointRanking d : rankings) {
                if (req.getUserId().equals(d.getUserId())) {
                    in = true;
                    uOrder = order;
                }
                RankingList rankingList = new RankingList();
                rankingList.setImageUrl(d.getImageUrl());
                rankingList.setName(d.getName());
                UserPO userPO1 = userPOHashMap.get(d.getUserId());
                this.setNickNameAndImage(userPO1, rankingList);
                if (Objects.nonNull(d.getQuantity())) {
                    BigDecimal b = new BigDecimal(d.getQuantity());
                    Double q = b.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
                    rankingList.setQuantity(q);
                }
//                rankingList.setRank(activityInfo.getRewardValueUnitDesc());
                rankingList.setOrderNo(orderNN);
                rankingLists.add(rankingList);
                order++;
                orderNN++;
            }
            rankingListResVO.setDatas(rankingLists);
            rankingListResVO.setInRanking(in);
            // 查询用户
            Query queryU = new Query();
            queryU.addCriteria(Criteria.where("userId").is(req.getUserId()).and(
                    "activityId").is(req.getActivityId()));
            UserPointRanking day = mongoTemplate.findOne(queryU, UserPointRanking.class);
            if (Objects.isNull(day)) {
                rankingListResVO.setOrderNo(0);
                rankingListResVO.setQuantity(0.0D);
            } else {
                rankingListResVO.setOrderNo(uOrder);
                rankingListResVO.setQuantity(day.getQuantity());
            }
            this.setRankName(rankingListResVO, userPO);
            this.setDefaultHead(rankingListResVO, req.getUserPO().getAvatarUrl());
            rankingListResVO.setInRanking(in);
            rankingListResVO.setPage(req.getPage());
            rankingListResVO.setPageSize(req.getPageSize());
            rankingListResVO.setTotalPages(count.intValue() / req.getPageSize() + 1);
            log.info(":>>> 全国积分排行榜结果:{}, 排行榜大小:{},排行榜数据:{}", count.intValue() / req.getPageSize() + 1, rankingListResVO.getDatas() == null ? 0 : rankingListResVO.getDatas().size(), JSON.toJSONString(rankingListResVO));
        } catch (Exception e) {
            log.error(":>>> 获取积分排行榜错误:{}", e);
        }
        return rankingListResVO;
    }

    private void setNickNameAndImage(UserPO userPO1, RankingList d) {
//        log.info(":>>> 开始设置头像:{},昵称:{}", d.getImageUrl(), d.getName());
        if (StringUtils.isBlank(d.getImageUrl())) {
            if (Objects.nonNull(userPO1)) {
                if (StringUtils.isNotBlank(userPO1.getAvatarUrl())) {
                    d.setImageUrl(userPO1.getAvatarUrl());
                } else {
                    d.setImageUrl(com.youlu.campus.base.base.Constants.defaultHead);
                }

            }

        }
        if (StringUtils.isBlank(d.getName())) {
            if (Objects.nonNull(userPO1)) {
                if (StringUtils.isNotBlank(userPO1.getNickName())) {
                    d.setName(userPO1.getNickName());
                } else {
                    if (StringUtils.isNotBlank(userPO1.getName())) {
                        if (userPO1.getName().length() >= 2) {
                            String s = userPO1.getName().substring(1);
                            d.setName(s);
                        } else {
                            d.setName(userPO1.getName());
                        }

                    }

                }

            }
        }
    }

    private void setDefaultHead(RankingListResVO rankingListResVO, String imageUrl) {


        if (StringUtils.isNotBlank(imageUrl)) {
            rankingListResVO.setImageUrl(imageUrl);
        } else {
            rankingListResVO.setImageUrl(defaultHead);
        }
    }

    /**
     * 设置用户名
     *
     * @param req
     * @param userPo
     */
    private void setRankName(RankingListResVO req, UserPO userPo) {
        try {
            if (Objects.nonNull(userPo)) {
                if (StringUtils.isNotBlank(userPo.getNickName())) {
                    req.setName(userPo.getNickName());
                } else if (StringUtils.isNotBlank(userPo.getName())) {
                    req.setName(userPo.getName());
                }
            }
        } catch (Exception e) {
            log.error(":>>> 设置排行榜名字错误:{}", e);
        }
    }

}
